package edu.xlh.travel.service.impl;

import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.ChineseGifCaptcha;

import edu.xlh.travel.common.Result;
import edu.xlh.travel.service.CaptchaService;
import edu.xlh.travel.util.BaiDuOCR;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Service
public class CaptchaServiceImpl implements CaptchaService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;


    @Override
    public Result getArithmeticCaptcha () throws ExecutionException, InterruptedException {
        //SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
        Map<String, String> keyAndValueMap = new HashMap<String, String>();
        ArithmeticCaptcha arithmeticCaptcha = new ArithmeticCaptcha(130, 48);
        arithmeticCaptcha.setLen(3);  // 几位数运算，默认是两位
        arithmeticCaptcha.getArithmeticString();  // 获取运算的公式：3+2=?
        String computeResult = arithmeticCaptcha.text();
        String key = UUID.randomUUID().toString();
        //耗时，在同时storeCaptchaToRedis和keyAndValueMapSet导致storeCaptchaToRedis率先返回，前端页面收不到验证码，导致（不断刷新验证码验证码不显示）redis和前端验证码数据不一致问题
        //因此提上来，串行执行
        String base64 = arithmeticCaptcha.toBase64();
        CompletableFuture<Void> storeCaptchaToRedis = CompletableFuture.runAsync(()->{
            // 存入redis并设置过期时间为1分钟
            /*redisTemplate.opsForValue().set(key,chineseGifCaptcha.text(),1, TimeUnit.MINUTES);*/
            // 将key和base64返回给前端
            List<Long> List = redisTemplate.executePipelined(new RedisCallback<Long>() {
                @Nullable
                @Override
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.openPipeline();
                    connection.set(key.getBytes(), computeResult.getBytes());
                    connection.expire(key.getBytes() , 300L);
                    return null;
                }
            },null);
        },threadPoolTaskExecutor);
        // 存入redis并设置过期时间为1分钟
        //redisTemplate.opsForValue().set(key,computeResult,1, TimeUnit.MINUTES);
        // 将key和base64返回给前端
        CompletableFuture<Void> keyAndValueMapSet = CompletableFuture.runAsync(()->{
        keyAndValueMap.put("key" , key);
        keyAndValueMap.put("value" , base64);
        },threadPoolTaskExecutor);
        //就get keyAndValueMapSet，不用get storeCaptchaToRedis,运气好的话keyAndValueMapSet率先返回，
        // 不好的话storeCaptchaToRedis先返回，redis有值
        //前端没有验证码图片就搞笑了
        //所以这样保证前端一定有验证码返回，redis异步，等我们输入验证码登录的时候redis已经存进去了
        //不get就是全程异步，数据没存入就返回了用户可能拿不到验证码(有可能redis没存，前端也没数据)
        CompletableFuture.anyOf( keyAndValueMapSet).get();
        return new Result(200,keyAndValueMap);
    }

    @Override
    public Result getChineseGifCaptcha() throws ExecutionException, InterruptedException {
        ChineseGifCaptcha chineseGifCaptcha = new ChineseGifCaptcha(130, 48);
        Map<String, String> keyAndValueMap = new HashMap<String, String>();
        String key = UUID.randomUUID().toString();
        String base64 = chineseGifCaptcha.toBase64();
        CompletableFuture<Void> storeCaptchaToRedis = CompletableFuture.runAsync(()->{
            // 存入redis并设置过期时间为1分钟
            /*redisTemplate.opsForValue().set(key,chineseGifCaptcha.text(),1, TimeUnit.MINUTES);*/
            // 将key和base64返回给前端
            List<Long> List = redisTemplate.executePipelined(new RedisCallback<Long>() {
                @Nullable
                @Override
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.openPipeline();
                    connection.set(key.getBytes(), chineseGifCaptcha.text().getBytes());
                    connection.expire(key.getBytes() , 300L);
                    return null;
                }
            },null);
        },threadPoolTaskExecutor);
        CompletableFuture<Void> keyAndValueMapSet = CompletableFuture.runAsync(()->{
            keyAndValueMap.put("key" , key);
            keyAndValueMap.put("value" , base64);
            keyAndValueMap.put("text" , chineseGifCaptcha.text());
        },threadPoolTaskExecutor);
       CompletableFuture.anyOf( keyAndValueMapSet).get();
        return new Result(200,keyAndValueMap);
    }

    @Override
    public Result fillVercodeByButton(String base64) {
        base64 = base64.replaceAll("\r\n", "");
        base64 = base64.replaceAll("\\+", "%2B");
        //百度云的文字识别接口,后面参数为获取到的token
        String httpUrl = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token="+ BaiDuOCR.getAuth();
        //id_card_side=front 识别正面    id_card_side=back  识别背面
        String httpArg = "detect_direction=true&id_card_side=front&image=" + base64;
        String jsonResult = BaiDuOCR.request(httpUrl, httpArg);
        System.out.println("返回的结果--------->" + jsonResult);
        //HashMap<String, String> map = BaiDuOCR.getHashMapByJson(jsonResult);
        return new Result(200 , "识别成功" ,  jsonResult);
    }
}
